#ifndef _FIBER_H_
#define _FIBER_H_

#include <iostream>
#include <functional>
#include <ucontext.h>
#include <cassert>


/**
 *@brief 协程类 
 */
class Fiber : public std::enable_shared_from_this<Fiber>{
public:

    typedef std::shared_ptr<Fiber> ptr;
    // 协程状态
    enum State{
        READY,     // 就绪态，刚创建或yield之后的状态
        RUNNING,   // 执行态，resume之后的状态
        TERM       // 结束态， 协程的回调函数执行完成之后的状态
    };

private:
    // 无参构造，仅由GetThis调用，创建主协程
    Fiber();

public:
    Fiber(std::function<void()> cb, size_t stack_size = 0, bool run_in_scheduler = true);
    ~Fiber();

    // 对协程进行重用
    void reset(std::function<void()> cb);
    
    // 任务协程恢复执行
    void resume();
    // 任务协程让出执行权
    void yield();

    uint64_t getId() const {return m_id;}

    State getState() const {return m_state;}

public:  // 一些静态函数

    // 设置当前运行的协程
    static void SetThis(Fiber *f);  

    // 获取当前运行的协程
    static Fiber::ptr GetThis();

    // 协程函数
    static void MainFunc();

    // 得到当前运行的协程id
    static uint64_t GetFiberId();

    // 设置调度协程（默认为主协程）
	static void SetSchedulerFiber(Fiber* f);

private: 
    // id
    uint64_t m_id = 0;
    
    // 栈大小
    uint64_t m_stacksize = 0;
    
    // 协程状态
    State m_state = READY;
    
    // 协程上下文
    ucontext_t m_ctx;
    
    // 协程的栈指针
    void *m_statck = nullptr;

    // 协程函数
    std::function<void()> m_cb;
    
    // 是否让出执行权给调度协程
    bool m_runInScheduler;

private:
    std::mutex m_mutex;

};

#endif